﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;

namespace KiDS_Projekat
{


	public class Program
	{

		public static string IpToText(uint ipAddr)
		{
			return (ipAddr & 0xFF) + "." + ((ipAddr >> 8) & 0xFF) + "." + ((ipAddr >> 16) & 0xFF) + "." + ((ipAddr >> 24) & 0xFF);
		}
		public static TerminalConnector Terminal;
		public static bool ParseResponse(string message, Node myNode)
		{
			bool myNodeFound = false;
			List<Master> mastersToInform = new List<Master>();
			string[] parts = message.Split(' ');
			string code = parts[0];
			
			if (code != CMD.CMD_REPLY_FAIL.ParseInt())
			{
				var masters = parts[1].Split(';');
				foreach (var location in masters)
				{
					var parameters = location.Split(':');
					if (parameters[2] != myNode.Location)
					{
						if (myNodeFound && (parameters[0] == myNode.Address && parameters[1] == myNode.Port + ""))
						{
							//check addr and port
							//add master level
							myNode.SetMaster(parameters[2].Split(',')[0], true);
							
						}
						else
						{
							//send register command to master
							ushort port = (ushort) Int16.Parse(parameters[1]);
							Master master = new Master(IpToText((uint)Int64.Parse(parameters[0])), port, parameters[2]);
							myNode.AddMaster(parameters[2].Split(',')[0], master);
							mastersToInform.Add(master);
							Console.WriteLine("Adding master to inform: " + master.ToString());
						}
					}
					else {
						myNodeFound = true;
						myNode.Address = IpToText((uint)Int64.Parse(parameters[0]));

					}
				}
				int m = 0;
				if (myNodeFound)
					m = 1;
				try
				{
					mastersToInform.RemoveAll(x => x.Address == myNode.Address && x.Port == myNode.Port);
					new Task(() =>
					{
						foreach (var master in mastersToInform)
						{
							Console.WriteLine("Master port/addr: " + master.Port + ", " + master.Address);
							if (master.Address == "0.0.0.0")
								master.Address = "127.0.0.1";
							Client client = new Client(master.Address, master.Port);
							client.Open();

							client.SendMessage("103 " + myNode.Location + ":" + m + ":" + myNode.Port);
							Program.Terminal.Print(client.RecieveMessage());
							client.Close();
						}
					}).Start();

				}
				catch
				{
					Console.WriteLine("Task exception");
				}
			
				return true;
			}
			
			return false;
		}

		static void Main(string[] args)
		{

			Console.WriteLine("Starting up!");
			var location = Properties.Settings.Default.Location;
			var port = Properties.Settings.Default.Port;
			var bLocation = Properties.Settings.Default.BootstrapLocation;
			var bPort = Properties.Settings.Default.BootstrapPort;
			Node myNode = new Node(location, port);
			Terminal = new TerminalConnector(myNode);
			TemperatureThreadTimer temperature = new TemperatureThreadTimer(myNode);
			
			Native native = new Native();

			Client client = new Client(bLocation, bPort);
			client.Open();
			client.SendMessage((int)CMD.CMD_BOOTSTRAP_REGISTER_SERVENT + " " + port + ":" + location);
			string retMsg = client.RecieveMessage();
			Console.WriteLine(retMsg);
			client.Close();

			if (!ParseResponse(retMsg, myNode)) {
				Console.WriteLine("Servent with the same location already exists. Closing socket...");
				Console.ReadLine();
				return;
			}

			Server server = new Server("192.168.21.100", Properties.Settings.Default.Port, myNode);
			server.Listen();
		
			Console.ReadLine();

		}
	}


	
}
